package util.bio.xamer;
import java.util.*;
/**
 * Counts the frequency of random words in a list of sequences.
 *
 */
public class XamerCounter {

	public XamerCounter(){

		//generate hexamers
		//String[] hexamers = hexamerGenerator();
		String[] pentamers = pentamerGenerator();
		
		//load selex oligo's by round
		String[][] seqs = fetchSequences(new String[]{
"/Users/nix/SelexData/DupFilteredSelexData/noProt/ParsedFiles/noPro1.SSPFasta",
"/Users/nix/SelexData/DupFilteredSelexData/noProt/ParsedFiles/noPro2.SSPFasta",
"/Users/nix/SelexData/DupFilteredSelexData/noProt/ParsedFiles/noPro3.SSPFasta",
"/Users/nix/SelexData/DupFilteredSelexData/noProt/ParsedFiles/noPro4.SSPFasta"});
		
		int[] totals = calculateTotalNumberOfOligosPerRound(seqs);
		
		
		
		//for each hexamer look for hits in seqs making a Xamer object if found
		ArrayList foundXamers = searchForXamers(pentamers, seqs);
		
		//set refs to reverse complementary xamer
		setRevCompRefs(foundXamers);
		
		//print the Xamers
		for (int i=foundXamers.size()-1; i>=0; i--){
			System.out.println(((Xamer)foundXamers.get(i)).toStringPercent(totals));
			//System.out.print(((Xamer)foundXamers.get(i)).toStringBarGraph(totals));
		}
		
						
		
	}
	/**Set refs to reverse comp xamer*/
	public void setRevCompRefs(ArrayList xamers){
		ArrayList copy = (ArrayList)xamers.clone();
		int len = copy.size();
		int counter = 1;
		while (copy.size()!=0){
			Xamer x = (Xamer)copy.remove(0);
			String revCompX = reverseCompDNA(x.getXamer());
			for (int j=copy.size()-1; j>=0; j--){
				Xamer y = (Xamer)copy.get(j);
				if (revCompX.equals(y.getXamer())){
					x.setRevCompRef(y);
					y.setRevCompRef(x);
					copy.remove(j);
					break;
				}
			}
		}
	}
	public static String reverseCompDNA(String seq){
		/**takes DNA seq and reverse comps it ambiguous symbols OK.
		 * Will warn if it finds an unrecognized base.  Works with ' GATCRYWSKMBDHVNX .- '
		 * upper or lower case*/
		int seqLen = seq.length();
		StringBuffer rcSeq = new StringBuffer(seqLen);
		char test;
		for (int i=seqLen-1; i>=0; i--){
			test = seq.charAt(i);
			switch (test){
				case 'a': rcSeq.append('t'); break;
				case 'A': rcSeq.append('T'); break;
				case 'c': rcSeq.append('g'); break;
				case 'C': rcSeq.append('G'); break;
				case 'g': rcSeq.append('c'); break;
				case 'G': rcSeq.append('C'); break;
				case 't': rcSeq.append('a'); break;
				case 'T': rcSeq.append('A'); break;
				case 'n':
				case 'N':
				case 'x':
				case 'X':
				case '-':
				case '.':
				case ' ':
				case 'S':
				case 's':
				case 'w':
				case 'W': rcSeq.append(test); break;
				case 'r': rcSeq.append('y'); break;
				case 'R': rcSeq.append('Y'); break;
				case 'y': rcSeq.append('r'); break;
				case 'Y': rcSeq.append('R'); break;
				case 'm': rcSeq.append('k'); break;
				case 'M': rcSeq.append('K'); break;
				case 'k': rcSeq.append('m'); break;
				case 'K': rcSeq.append('M'); break;
				case 'b': rcSeq.append('v'); break;
				case 'B': rcSeq.append('V'); break;
				case 'd': rcSeq.append('h'); break;
				case 'D': rcSeq.append('H'); break;
				case 'h': rcSeq.append('d'); break;
				case 'H': rcSeq.append('D'); break;
				case 'v': rcSeq.append('b'); break;
				case 'V': rcSeq.append('B'); break;
				default: rcSeq.append(test); System.err.println("\nWarning: odd base in revComp-> '"+test+
				"' Reverse Complement possibly incorrect!\n");
			}
		}
		return rcSeq.toString();
	}	
	
	/**Creates an ArrayList of Xamer objects, where each Xamer contains all the seqs, by round
	 * that were found to match a particular xamers[i]*/
	public static ArrayList searchForXamers(String[] xamers, String[][] seqs){	
		ArrayList foundXamers = new ArrayList();
		int numXamers = xamers.length;
		int numRnds = seqs.length;
		for (int i=numXamers-1; i>=0; i--){
			Xamer x = new Xamer();
			ArrayList xHits = x.getSelexOligos();
			boolean hasHits = false;
			//look for hits in each round, round ordering is important here
			for (int j=0; j<numRnds; j++){
				ArrayList hits = findSequenceHits(seqs[j],xamers[i]);
				xHits.add(hits);
				if (hits.size()!=0) hasHits = true;
			}
			if (hasHits) {
				x.setXamer(xamers[i]);
				foundXamers.add(x);
				} 
		}
		return foundXamers;
	}								

	public int[] calculateTotalNumberOfOligosPerRound(String[][] seqs){
		int len = seqs.length;
		int[] totals = new int[len];
		for (int i=0; i<len; i++){
			totals[i]= seqs[i].length;
		}
		return totals;
	}
	
	
	/**Looks for an exact match of the oligo to each of the seqs, returning the seqs that contain
	 * the oligo*/
	public static ArrayList findSequenceHits(String[] seqs, String oligo){
		ArrayList hits = new ArrayList();
		int len = seqs.length;
		for (int i= len-1; i>=0; i--){
			if (seqs[i].indexOf(oligo)!= -1) hits.add(seqs[i]);
		}
		return hits;
	}
	
	/**Fetch all sequences from each multi-FASTA file*/
	public static String[][] fetchSequences(String[] files){
		int len = files.length;
		String[][] seqs = new String[len][];
		for (int i=0; i<len; i++) seqs[i] = (new util.bio.parsers.MultiFastaParser(files[i])).getSeqs();			
		return seqs;
	}
	//Constructor
	public static void main(String[] args) {
		new XamerCounter();
	}	
	public static String[] hexamerGenerator(){
		String[] nt = { "G", "A", "T", "C" };
		String[] hexamers = new String[4096];
		int i=0;
		for (int a = 3; a >= 0; a--) {
			for (int b = 3; b >= 0; b--) {
				for (int c = 3; c >= 0; c--) {
					for (int d = 3; d >= 0; d--) {
						for (int e = 3; e >= 0; e--) {
							for (int f = 3; f >= 0; f--) {
								hexamers[i] = nt[a]+ nt[b]+ nt[c]+ nt[d]+ nt[e]+ nt[f];
								i++;
							}}}}}}
		return hexamers;
	}
	public static String[] pentamerGenerator(){
		String[] nt = { "G", "A", "T", "C" };
		String[] pentamers = new String[1024];
		int i=0;
		for (int a = 3; a >= 0; a--) {
			for (int b = 3; b >= 0; b--) {
				for (int c = 3; c >= 0; c--) {
					for (int d = 3; d >= 0; d--) {
						for (int e = 3; e >= 0; e--) {
							pentamers[i] = nt[a]+ nt[b]+ nt[c]+ nt[d]+ nt[e];
								i++;
							}}}}}
		return pentamers;
	}
	
	
}

